home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 98
/
Skunkware 98.iso
/
src
/
interp
/
tclStruct1.2.tar.gz
/
tclStruct1.2.tar
/
tclStruct1.2
/
stObject.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-12
|
6KB
|
224 lines
/*
* tclStruct package
* Support 'C' structures in Tcl
*
* Written by Matthew Costello
* (c) 1995 AT&T Global Information Solutions, Dayton Ohio USA
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "stInternal.h"
STRUCT_SCCSID("@(#)tclStruct:stObject.c 1.1 95/09/08")
/*
* generate uniq Id
*/
CONST char *
Struct_GenerateName(base)
CONST char *base;
{
static int id=1;
static char name[16];
sprintf(name,"%.10s%d",base,id++);
return name;
}
#ifdef DEBUG
CONST char *
Struct_ObjectName(object,inclobjaddr)
Struct_Object *object;
int inclobjaddr;
{
static char namebuf[128];
if (inclobjaddr)
sprintf(namebuf,"%p[%s,%p/%ld,%d]",
(void *)object,
Struct_TypeName(object->type),
object->data,
(long) object->data,
object->size );
else
sprintf(namebuf,"[%s,%p/%ld,%d]",
Struct_TypeName(object->type),
object->data,
(long)object->data,
object->size );
return namebuf;
}
#endif
/*
* Struct_NewObject : creates a new binary object
* if the dataptr argument is NULL, allocate the data part too
* if the size is 0, then use the size of the type
*/
Struct_Object *
Struct_NewObject(type,dataptr,size)
Struct_TypeDef *type;
void *dataptr;
int size;
{
int len;
Struct_Object *object;
#ifdef DEBUG
if (struct_debug & (DBG_NEWOBJECT))
printf("Struct_NewObject( %s, ptr = %p, size = %d )\n",
Struct_TypeName(type), dataptr, size );
#endif
len = sizeof(Struct_Object);
if (size == 0)
size = type->size;
/* If dataptr is null, allocate the data and the end of
* of the object structure. */
if (dataptr == NULL)
len += size;
if ((object = (Struct_Object *)ckalloc(len)) == NULL) {
return NULL;
}
memset( (char *)object, 0x00, len );
#ifdef STRUCT_MAGIC
object->magic = STRUCT_MAGIC_OBJECT;
#endif
if (dataptr == NULL)
dataptr = (object + 1);
object->data = dataptr;
object->size = size;
Struct_AttachType(type);
object->type = type;
#ifdef DEBUG
if (struct_debug & (DBG_NEWOBJECT))
printf("Struct_NewObject() = %s\n", Struct_ObjectName(object,1) );
#endif
return object;
}
/*
* Create a new object
*
* usage : struct_new object|#auto type ?existingobject?
*
*/
int
Struct_NewCmd(cdata, interp, argc, argv)
ClientData cdata; /* Client Data */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
Struct_Object *objptr;
Struct_TypeDef *type;
char *name;
Struct_Object oldobj;
if (cdata==NULL) {
Tcl_AppendResult(interp, "Called Struct_NewCmd with NULL client data",NULL);
return TCL_ERROR;
}
Struct_PkgInfo(cdata,si_cmdCount) += 1;
if (argc<3 || argc>4) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" object|#auto type ?oldobject?\"", (char *) NULL);
return TCL_ERROR;
}
#ifdef DEBUG
if (struct_debug & (DBG_COMMAND)) Struct_PrintCommand(argc,argv);
#endif
name = (strcmp(argv[1],"#auto") == 0) ?
(char *)Struct_GenerateName(argv[2]) : argv[1];
/* check object is not already defined (like in GetObject, but reversed
error condition */
if (STRUCT_GETOBJECT(interp,name)) {
Tcl_AppendResult(interp,"\"",name,"\" is already an object",NULL);
return TCL_ERROR;
}
/* The type must be defined. */
if ((type = Struct_LookupType(cdata,interp,argv[2])) == NULL)
return TCL_ERROR;
/* The type has to have a known size, so it cannot have a variable
* length type if we need to create it. If the object already
* exists then we can get away with a variable length type.
*/
if (argc < 4) {
oldobj.data = NULL;
oldobj.size = 0;
if (type->flags & STRUCT_FLAG_VARLEN) {
Tcl_AppendResult(interp,"\"",argv[2],"\" is a variable length type",NULL);
return TCL_ERROR;
}
} else if (Struct_GetObject(interp,argv[3],&oldobj) != TCL_OK) {
Struct_ReleaseType(type);
return TCL_ERROR;
} else if (type->size > oldobj.size) {
Tcl_AppendResult(interp,"\"",argv[2],"\" is too small",NULL);
return TCL_ERROR;
} else if ( (type->flags & STRUCT_FLAG_VARLEN) &&
!(oldobj.type->flags & STRUCT_FLAG_VARLEN) ) {
/* Instantiate type to correct length */
Struct_TypeDef *vartype;
#ifdef DEBUG
if (struct_debug & (DBG_VARLEN))
printf("Struct_NewCmd: calculating how to instantiate %s into %d bytes\n",
Struct_TypeName(type), oldobj.size );
#endif
for (vartype = type; vartype->flags & STRUCT_FLAG_IS_STRUCT; ) {
#ifdef DEBUG
if (struct_debug & (DBG_VARLEN))
printf("Struct_NewCmd: following %s\n",Struct_TypeName(vartype));
#endif
vartype = vartype->u.s.struct_def[vartype->u.s.num_elements -1].type;
}
type = Struct_InstantiateType(cdata,interp,NULL,type,
(oldobj.size - type->size) / vartype->u.a.array_elem->size );
}
/* Allocate the object. */
objptr = Struct_NewObject(type,oldobj.data,oldobj.size);
Struct_ReleaseType(type);
if (objptr == NULL) {
Tcl_SetResult(interp,"Can't allocate object!",TCL_STATIC);
return TCL_ERROR;
}
/* Create the array and attach our trace to control element access */
if (Tcl_SetVar2(interp,name,"_type_",argv[2],TCL_LEAVE_ERR_MSG)==NULL)
return TCL_ERROR;
Tcl_TraceVar2(interp,name,NULL,
TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
Struct_MainTraceProc,objptr);
Tcl_SetResult(interp,name,TCL_VOLATILE);
return TCL_OK;
}
/*******************************************************************/
/*
* Delete Object
*
*/
void
Struct_DeleteObject(object)
Struct_Object *object;
{
if (object != NULL) {
Struct_CheckObject(object,"DeleteObject");
#ifdef DEBUG
if (struct_debug & (DBG_NEWOBJECT))
printf("Struct_DeleteObject( %s )\n", Struct_ObjectName(object,1) );
#endif
Struct_ReleaseType(object->type);
ckfree((char *)object);
}
}